/* 
 *  Copyright (C) 2007 Dip. Ing. dell'Informazione, University of Pisa, Italy
 *  http://info.iet.unipi.it/~cng/ns2voip/
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, USA
 */
/*
 */

#ifndef __NS2_VOIP_BIDIRECTIONAL_H
#define __NS2_VOIP_BIDIRECTIONAL_H

#include <object.h>
#include <t_timers.h>
#include <ranvar.h>

class VoipSource;

class VoipBidirectional : public TclObject {
public:
        //! Create an empty VoIP bidirectional module.
        VoipBidirectional ();

        //! Return true if the object is ready to be started.
        bool initialized () { return ( nsources_ == 2 ) && initialized_; } 

        //! Tcl interface.
        /*!
         * Tcl commands:
         * - $obj debug\n
         *   Enable debug to standard error.
         * - $obj nodebug\n
         *   Disable debug to standard error (default).
         */
        virtual int command (int argc, const char*const* argv);

        //! Generate a new talkspurt.
        virtual void next (VoipSource* source, double& talk, double& silence)
			  { abort(); }

protected:
        //! Pointer to the encoder application.
        VoipSource* source_[2];
		  //! Pointer to the bidirectional module, if present.
		  VoipBidirectional* bidirectional_;
		  //! Current number of sources. When initialized is equal to two.
		  unsigned int nsources_;
		  //! True if debug is enabled.
		  bool debug_;
		  //! True if debug is enabled.
		  bool initialized_;
};

/*
 *  Finite State Machine:
 *
 *   /-------------\        p1        /--------------\
 *  |               | -------------> |                |
 *  | Single Talk A |       p2       | Mutual silence |
 *  |               | <------------- |                |
 *   \-------------/                  \--------------/
 *     / \     |                        / \      |
 *      |      |                         |       |
 *      | 1-p3 | 1-p1                    | 1-p4  | 1-p2
 *      |      |                         |       |
 *      |     \ /                        |      \ /
 *   /-------------\        p3        /--------------\
 *  |               | -------------> |                |
 *  | Double Talk   |       p4       | Single Talk B  |
 *  |               | <------------- |                |
 *   \-------------/                  \--------------/
 *
 *
 *  E[Single Talk]    = 1.004 s
 *  E[Double Talk]    = 0.228 s
 *  E[Mutual Silence] = 0.508 s
 * 
 */
class VoipBidirectionalItuP59 : public VoipBidirectional {
	enum State { TALK_A, TALK_B, DOUBLE_TALK, MUTUAL_SILENCE };

public:
	//! Create a default bi-directional source according to ITU-T P.59.
	VoipBidirectionalItuP59();

	//! Tcl interface.
	//virtual int command (int argc, const char*const* argv);

	//! Generate a new talkspurt.
	//virtual void next (VoipSource* source, double& talk, double& silence) {}

protected:
	//! Timer to schedule talkspurts.
	//TTimer<VoipBidirectionalItuP59> timer_;
	//! Random variable for single talk user A.
	ExponentialRandomVariable singleTalkA_;
	//! Random variable for single talk user B.
	ExponentialRandomVariable singleTalkB_;
	//! Random variable for double talk.
	ExponentialRandomVariable doubleTalk_;
	//! Random variable for mutual silence.
	ExponentialRandomVariable mutualSilence_;
	
	//! Current state.
	State state_;

	//! TODO

};

#endif // __NS2_VOIP_BIDIRECTIONAL_H
